package org.wx.io.netty.simple;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.AbstractChannel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.FixedLengthFrameDecoder;
import io.netty.util.NettyRuntime;
import lombok.extern.slf4j.Slf4j;

/**
 * @description: netty server
 * @author: wangxun
 * @createDate: 2021/2/7
 * @version: 1.0
 */
@Slf4j
public class NettyServer {
    public static void main(String[] args) {

        /*
           参数为线程数量，如果不写默认是cpu核数*2
           NettyRuntime.availableProcessors() * 2
         */

        log.info("cpu核数*2：{}", NettyRuntime.availableProcessors() * 2);
        NioEventLoopGroup boss = new NioEventLoopGroup();
        NioEventLoopGroup worker = new NioEventLoopGroup();
        try {
            // netty Server 脚手架
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boss, worker)
                    .channel(NioServerSocketChannel.class) // 利用反射获取channel实现类
                    // 添加初始化末班的handler,ChannelInitializer 为共享的@Sharable
                    // @Sharable 表示此handler可以被多个pipeline共享的（单例）
                    // 如果不添加 @Sharable 那么就会报错
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ch.pipeline().addFirst(new FixedLengthFrameDecoder(13));
                            ch.pipeline().addLast(new ServerHandler());
                        }
                    });
            // 同步等待bind完成后
            ChannelFuture channelFuture = serverBootstrap.bind(9999).sync();
            channelFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    log.info("开启监听....");
                }
            });
            // 对ServerSocketChannel通道关闭进行监听
            ChannelFuture closeFuture = channelFuture.channel().closeFuture().sync();
            closeFuture.addListener(new ChannelFutureListener() {
                @Override
                public void operationComplete(ChannelFuture future) throws Exception {
                    log.info("server listen is work...");
                    if(future.isDone()){
                        log.info("{} is closed...",future.channel().localAddress());
                    }
                }
            });
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            // 优雅的关闭
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}
